/*******************************************************************************
 * Copyright 2007 Vidar Svansson
 *     
 * This file is part of JAdapter.
 * 
 * JAdapter is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * JAdapter is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with JAdapter.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/


package org.jadapter.tests;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

import junit.framework.TestCase;

import org.jadapter.JAdapter;
import org.jadapter.Transformer;
import org.jadapter.registry.AdapterRegistry;
import org.jadapter.registry.TransitiveAdapterRegistry;
import org.jadapter.tests.examples.ArbitarySetterAdapter;
import org.jadapter.tests.examples.ConstructorAdapter;
import org.jadapter.tests.examples.Csv;
import org.jadapter.tests.examples.FactoryMethodAdapter;
import org.jadapter.tests.examples.SetterAdapter;
import org.jadapter.tests.examples.SortedMapList;
import org.jadapter.tests.examples.StaticFactoryAdapter;
import org.jadapter.tests.examples.SubclassDependencyAdapter;
import org.jadapter.tests.examples.TransformerAdapter;

@SuppressWarnings("unchecked")
public class TestAdapters extends TestCase {
    
    Csv commas;    
    Map<String, String> map;    
    List<?> list;
    
    @Override
    public void setUp() {  
        map = new HashMap<String,String>();
        map.put("Foo", "foo");
        map.put("Bar", "bar");
        list = Arrays.asList("Foo", "Bar");
   }

    /* Test adapters that implement Adapter */
    public void testSelfAdapter() throws Exception {
                  
        // This wrapping is not really needed since
        // CommaSeparatedListAdapter is an Adapter
        JAdapter<Csv,List> adapter = 
            new JAdapter<Csv,List>
                (new SubclassDependencyAdapter());

        assertTrue(adapter.resolved());


        Object o = adapter.transform(list);
        assertTrue(o instanceof Csv);
        
        assertTrue(adapter.resolved());
        
        o = adapter.transform(list);
        
        commas = (Csv)o;
        String listCs = commas.csv();
        assertEquals("comma separated list", "Foo,Bar", listCs);
        assertTrue(adapter.resolved());

        
        // So we can also just skip the use of JAdapter
        Transformer<Csv,List> adapter1 = new SubclassDependencyAdapter();
        commas = adapter1.transform(list);
        listCs = commas.csv();
        assertEquals("comma separated list", "Foo,Bar", listCs);		
    }


    public void testSetterAdapter() throws Exception {
        JAdapter<Csv,List> adapter = new JAdapter<Csv,List> (
                SetterAdapter.class,
                Csv.class,
                List.class);
        
        assertFalse(adapter.resolved());
        commas = adapter.transform(list);
        assertTrue(adapter.resolved());

        String listCs = commas.csv();
        assertEquals("comma separated list", "Foo,Bar", listCs);
    }


    public void testConstructorAdapter() throws Exception {
        JAdapter<Csv,Map> adapter = new JAdapter<Csv,Map> (
                ConstructorAdapter.class,
                Csv.class,
                Map.class);
        
        
        assertFalse(adapter.resolved());

        commas = adapter.transform(map);
        assertTrue(adapter.resolved());

        String listCs = commas.csv();
        assertEquals("comma separated map", "Foo:foo,Bar:bar", listCs);
    }	

    public void testStaticFactoryAdapter() throws Exception {
        JAdapter<Csv,List> a =
            new JAdapter<Csv,List>();
        
        a.setFactory(StaticFactoryAdapter.class);
        a.to(Csv.class);
        a.from(List.class);
        assertFalse(a.resolved());

        Csv cs = a.transform(list);
        assertTrue(a.resolved());

        String s = cs.csv();
        assertEquals("comma separated list", "Foo,Bar", s);
    }


    @SuppressWarnings("unchecked")
    public void testNonGeneric() throws Exception {
        JAdapter adapter = new JAdapter();
        adapter.to(Csv.class);
        adapter.from(List.class);
        adapter.setFactory(SetterAdapter.class);
        assertFalse(adapter.resolved());

        // we need to cast the result since we are not using generics here
        commas = (Csv)adapter.transform(list);
        assertTrue(adapter.resolved());

        String listCs = commas.csv();
        assertEquals("comma separated list", "Foo,Bar", listCs);        
    }	


    
    public void testShouldFindAdapterMethodWithCorrectSignature(){
        JAdapter<Csv,List> a =
            new JAdapter<Csv,List>();
        a.setFactory(FactoryMethodAdapter.class);
        a.to(Csv.class);
        a.from(List.class);
        assertFalse(a.resolved());

        Csv cs = a.transform(list);
        assertTrue(a.resolved());

        String s = cs.csv();
        assertEquals("comma separated list", "Foo,Bar", s);

        
    }
    
    public void testArbitrarySetter() throws Exception {
        AdapterRegistry registry = new TransitiveAdapterRegistry();

        registry.register(ArbitarySetterAdapter.class, Csv.class, List.class);
        Csv cs = registry.transform(list, Csv.class);
        assertEquals("Foo,Bar", cs.csv());
    }
    
    public void testAdapter() throws Exception {
        AdapterRegistry registry = new TransitiveAdapterRegistry();

        registry.register(TransformerAdapter.class, Csv.class, List.class);
        Csv cs = registry.transform(list, Csv.class);
        assertEquals("Foo,Bar", cs.csv());        
    }
    
    public void testFunctionFactoryAdapter() throws Exception {
        AdapterRegistry registry = new TransitiveAdapterRegistry();

        Transformer<Csv,List> adapter = new Transformer<Csv,List>(){
            public Csv transform(final List item) {
                return new SetterAdapter(){{setList(item);}};
            }
        };     
        
        
        
        registry.register(adapter, Csv.class, List.class);      
        Csv cs = registry.transform(list, Csv.class);
        assertEquals("Foo,Bar", cs.csv());     
    }
    
    public void testMapList(){
        SortedMapList adapter = new SortedMapList();
        
        SortedMap map = adapter.transform(list);
        assertTrue(map.containsKey(1));
        assertTrue(map.containsValue("Foo"));
    }
        
}

